package com.yyhh.helpcall.utils;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.text.TextUtils;
import androidx.core.content.ContextCompat;
import com.yyhh.helpcall.MainApplication;
import com.yyhh.helpcall.http.OkHttpUtils;
import com.yyhh.helpcall.http.bean.BaseResponse;
import com.yyhh.helpcall.http.bean.LastUpdateResponse;
import com.yyhh.helpcall.model.CallModel;
import com.yyhh.helpcall.model.RecordModel;
import java.io.File;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;

public class ScanRecordUtils {

    public static final String SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath();
    public static boolean flag = false;
    public static int taskCount = 0;
    public static int count = 0;

    /**
     * 递归匹配录音文件
     *
     * @param recordModels 手机上全部的录音文件
     * @param result       接收数据的集合
     */
    public static void matchingRecords(int count,List<RecordModel> recordModels, ArrayList<RecordModel> result) {

        ArrayList<RecordModel> noResult = new ArrayList<>();

        for (int i = 0; i < recordModels.size(); i++) {
            RecordModel recordModel = recordModels.get(i);

            List<CallModel> callModels = recordModel.okFilterCallModels.size() > 0 ? recordModel.okFilterCallModels : recordModel.noFilterCallModels;

            for (int j = 0; j < callModels.size(); j++) {
                CallModel callModel = callModels.get(j);

                //录音文件最后一次的修改时间-通话开始时间
                long offset = recordModel.lastModifyTime - callModel.date;

                if (offset > 0
                        && callModel.duration > 0
                        && Math.abs((recordModel.lastModifyTime - (callModel.date + (callModel.duration - 1) * 1000))) <= offset * 1000
                ) {
                    //匹配到了，则添加到集合里
                    recordModel.targetCallModel = callModel;
                    result.add(recordModel);
                    break;
                }
            }

            //没匹配到则额外处理
            if (result.indexOf(recordModel) == -1) {
                noResult.add(recordModel);
            }
        }

        if(count > 5 * 60){
            return;
        }

        if (noResult.size() > 0) {
            //说明没有匹配上,则一一直匹配下去，直到所有都匹配成功
            matchingRecords(count + 2, noResult, result);
        }
    }

    /**
     * 上传录音文件
     */
    public static void uploadRecords(final Context context) {
        if (ScanRecordUtils.flag) return;
        ScanRecordUtils.flag = true;

        OkHttpUtils.getInstance().getApi().getLastRecordTime(new HashMap<>())
                .observeOn(Schedulers.io())
                .map(new Function<BaseResponse<LastUpdateResponse>, Long>() {

                    @Override
                    public Long apply(BaseResponse<LastUpdateResponse> value) throws Exception {
                        //获取最新的时间戳
                        long last_timestamp = 0;
                        if (value.isSuccess() && !TextUtils.isEmpty(value.data.last_timestamp)) {
                            last_timestamp = Long.parseLong(value.data.last_timestamp);
                        }

                        NetLog.d("录音记录的最新时间戳" + last_timestamp + ",当前线程" + Thread.currentThread().getName());
                        return last_timestamp;
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Function<Long, ArrayList<RecordModel>>() {
                    @Override
                    public ArrayList<RecordModel> apply(Long last_timestamp) throws Exception {
                        //扫描录音文件
                        ArrayList<RecordModel> recordModels = scanRecordFiles();

                        ArrayList<RecordModel> filterRecordModels = new ArrayList<>();
                        //过滤出匹配的录音文件
                        for (int i = 0; i < recordModels.size(); i++) {
                            RecordModel recordModel = recordModels.get(i);
                            if (recordModel.lastModifyTime > last_timestamp) {
                                filterRecordModels.add(recordModel);
                            }
                        }
                        //排序
                        Collections.sort(filterRecordModels, new Comparator<RecordModel>() {
                            @Override
                            public int compare(RecordModel o1, RecordModel o2) {
                                return (int) (o1.lastModifyTime - o2.lastModifyTime);
                            }
                        });
                        NetLog.d("总共扫描到了" + recordModels.size() + "条录音，匹配到了" + filterRecordModels.size() + "条,当前线程" + Thread.currentThread().getName());
                        return filterRecordModels;
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Function<ArrayList<RecordModel>, ArrayList<RecordModel>>() {
                    @Override
                    public ArrayList<RecordModel> apply(ArrayList<RecordModel> recordModels) throws Exception {
                        //扫描通话记录
                        List<CallModel> callModels = ScanCallLogUtils.startScanCallLogs(context);
                        ArrayList<RecordModel> result = new ArrayList<>();

                        //开始匹配对应的通话记录
                        for (int i = 0; i < recordModels.size(); i++) {
                            RecordModel recordModel = recordModels.get(i);
                            //格式化录音文件名称
                            String fileName = recordModel.name
                                    .replace(" ","")
                                    .replace("_","")
                                    .replace("@","")
                                    .replace("+","")
                                    .replace("-","");

                            for (int j = 0; j < callModels.size(); j++) {
                                CallModel callModel = callModels.get(j);
                                String number = callModel.number;
                                boolean flag = true;
                                if(!fileName.contains(number)){
                                    flag = false;
                                }

                                if(flag){
                                    recordModel.okFilterCallModels.add(callModel);
                                }else{
                                    recordModel.noFilterCallModels.add(callModel);
                                }
                            }
                        }

                        //由于linux没有文件创建时间的概念，所以目前是根据最后的修改时间做比较
                        //但有些手机上文件的最后修改时间误差比较大，所以需要递归循环去增加时间戳比较
                        matchingRecords(1,recordModels, result);

                        NetLog.d("总共匹配到了" + recordModels.size() + "条录音，实际匹配到了" + result.size() + "条,当前线程" + Thread.currentThread().getName());

                        taskCount = result.size();

                        if(taskCount == 0){
                            ScanRecordUtils.flag = false;
                        }
                        return result;
                    }
                })
                .observeOn(Schedulers.io())
                .flatMap(new Function<ArrayList<RecordModel>, ObservableSource<RecordModel>>() {
                    @Override
                    public ObservableSource<RecordModel> apply(ArrayList<RecordModel> recordModels) throws Exception {
                        return Observable.fromIterable(recordModels);
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Function<RecordModel, RecordModel>() {
                    @Override
                    public RecordModel apply(RecordModel recordModel) throws Exception {
                        //开始上传录音文件
                        File file = new File(recordModel.path);
                        String fileName = URLEncoder.encode(recordModel.name, "UTF-8");
                        RequestBody fileBody = RequestBody.create(MediaType.parse("application/otcet-stream"), file);
                        MultipartBody body = new MultipartBody.Builder()
                                .setType(MultipartBody.FORM)
                                .addFormDataPart("file", fileName, fileBody)
                                .build();
                        OkHttpUtils.getInstance().getApi().uploadFile(body)
                                .subscribe(new Observer<BaseResponse<Object>>() {
                                    @Override
                                    public void onSubscribe(Disposable d) {

                                    }

                                    @Override
                                    public void onNext(BaseResponse<Object> value) {
                                        if (value.isSuccess()) {
                                            recordModel.isUploadSuccess = true;
                                            NetLog.d("录音文件上传成功" + recordModel.name + ",当前线程" + Thread.currentThread().getName());
                                        } else {
                                            NetLog.d("录音文件上传失败" + recordModel.name + ",当前线程" + Thread.currentThread().getName());
                                        }
                                    }

                                    @Override
                                    public void onError(Throwable e) {
                                        e.printStackTrace();
                                        NetLog.d("录音文件上传失败");
                                    }

                                    @Override
                                    public void onComplete() {

                                    }
                                });
                        return recordModel;
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Function<RecordModel, RecordModel>() {
                    @Override
                    public RecordModel apply(RecordModel recordModel) throws Exception {
                        if (recordModel.isUploadSuccess) {
                            //添加录音记录
                            String fileName = URLEncoder.encode(recordModel.name, "UTF-8");

                            HashMap<String, String> map = new HashMap<>();
                            map.put("business_tel", SpUtils.getInstance(MainApplication.mainApplication).getString("account"));
                            map.put("customer_tel", recordModel.targetCallModel.number);
                            map.put("direction", recordModel.targetCallModel.callType + "");
                            map.put("timestamp", recordModel.lastModifyTime + "");
                            map.put("objname", fileName);
//                            map.put("name",recordModel.targetCallModel.name);
                            map.put("duration", recordModel.targetCallModel.duration + "");

                            OkHttpUtils.getInstance().getApi().postCallRecord(map)
                                    .subscribe(new Observer<BaseResponse<Object>>() {
                                        @Override
                                        public void onSubscribe(Disposable d) {

                                        }

                                        @Override
                                        public void onNext(BaseResponse<Object> value) {
                                            if (value.isSuccess()) {
                                                NetLog.d("录音记录添加成功" + recordModel.name + "手机号为" + recordModel.targetCallModel.number + ",当前线程" + Thread.currentThread().getName());
                                            } else {
                                                NetLog.d("录音记录添加失败" + recordModel.name + "手机号为" + recordModel.targetCallModel.number + ",当前线程" + Thread.currentThread().getName());
                                            }
                                        }

                                        @Override
                                        public void onError(Throwable e) {
                                            count ++;
                                            if(count == taskCount){
                                                flag = false;
                                                taskCount = 0;
                                                count = 0;
                                                NetLog.d("全部任务执行完成");
                                            }
                                        }

                                        @Override
                                        public void onComplete() {
                                            count ++;
                                            if(count == taskCount){
                                                flag = false;
                                                taskCount = 0;
                                                count = 0;
                                                NetLog.d("scanRecord 全部任务执行完成");
                                            }
                                        }
                                    });
                        }
                        return recordModel;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<RecordModel>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(RecordModel value) {
                        NetLog.d("录音文件同步完成" + value.toString() + ",当前线程" + Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    /**
     * 扫描录音文件
     *
     * @return
     */
    public static ArrayList<RecordModel> scanRecordFiles() {
        ArrayList<RecordModel> result = new ArrayList<>();
        if(TextUtils.isEmpty(MainApplication.recordConfig.path)){
            return result;
        }
        File parentFile = new File(MainApplication.recordConfig.path);
        if (parentFile == null || !parentFile.exists()) {
            return result;
        } else if (parentFile.isDirectory()) {
            File[] files = parentFile.listFiles();
            for (int i = 0; i < files.length; i++) {
                File file = files[i];

                if (file.getName().endsWith(".wav")
                        || file.getName().endsWith(".m4a")
                        || file.getName().endsWith(".amr")
                        || file.getName().endsWith(".mp3")) {
                    RecordModel recordModel = new RecordModel(file.getName(), file.getAbsolutePath(), MainApplication.recordConfig.suffix, file.lastModified(), "");
                    result.add(recordModel);
                }

//                if (file.getName().endsWith(MainApplication.recordConfig.suffix)) {
//                    RecordModel recordModel = new RecordModel(file.getName(), file.getAbsolutePath(), MainApplication.recordConfig.suffix, file.lastModified(), "");
//                    result.add(recordModel);
//                }
            }
        }



        return result;
    }

    /**
     * 检测是否开启通话录音功能
     *
     * @param callBack
     */
    public static void checkEnableRecords(final Context context, final EnableRecordsCallBack callBack) {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            if (callBack != null) {
                callBack.onSuccess(false);
            }
            return;
        }

        Observable.create(new ObservableOnSubscribe<ArrayList<RecordModel>>() {
            @Override
            public void subscribe(ObservableEmitter<ArrayList<RecordModel>> e) throws Exception {
                //扫描录音文件
                ArrayList<RecordModel> result = scanRecordFiles();
                e.onNext(result);
                e.onComplete();
            }
        })
                .observeOn(Schedulers.io())
                .map(new Function<ArrayList<RecordModel>, Boolean>() {
                    @Override
                    public Boolean apply(ArrayList<RecordModel> recordModels) throws Exception {
                        //扫描通话记录
                        List<CallModel> callModels = ScanCallLogUtils.startScanCallLogs(context);

                        List<CallModel> callModelDurations = new ArrayList<>();
                        for (int i = 0; i < callModels.size(); i++) {
                            CallModel callModel = callModels.get(i);
                            if (callModel.duration > 0) {
                                callModelDurations.add(callModels.get(i));
                            }
                        }

                        //如果有通话记录，但没有录音文件则判定为没有开启通话录音功能
                        if (callModelDurations.size() == 0 || recordModels.size() == 0) {
                            return false;
                        }

                        //取最新的通话记录，查找出对应的录音文件，如果没有找到判定为没有开启通话录音
                        for (int i = 0; i < recordModels.size(); i++) {
                            RecordModel recordModel = recordModels.get(i);
                            //根据时间比较
                            CallModel callModel = callModelDurations.get(0);
                            if (
                                    recordModel.lastModifyTime > callModel.date
                                    && Math.abs((recordModel.lastModifyTime - (callModel.date + (callModel.duration - 2) * 1000))) <= 3 * 60 * 1000) {
                                //找到了则认为开启了通话录音功能
                                return true;
                            }
                        }

                        return false;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Boolean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Boolean value) {
                        callBack.onSuccess(value);
                    }

                    @Override
                    public void onError(Throwable e) {
                        callBack.onFail(e);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }


    public interface ScanRecordsCallBack {

        void onSuccess(ArrayList<RecordModel> result);

        void onFail(Throwable e);
    }

    public interface EnableRecordsCallBack {

        void onSuccess(boolean enable);

        void onFail(Throwable e);
    }
}
